package com.bajiao.service.order.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.bajiao.common.constant.CouponStatusEnum;
import com.bajiao.common.constant._Whole;
import com.bajiao.common.exception.DataHandleException;
import com.bajiao.common.util.*;
import com.bajiao.common.util.encryption.AesEncryptUtil;
import com.bajiao.dto.coupon.CouponCountDto;
import com.bajiao.dto.coupon.CouponDto;
import com.bajiao.dto.order.ConfirmOrderRequest;
import com.bajiao.dto.order.CreateOrderRequest;
import com.bajiao.dto.order.EncodeMenuOrderDetails;
import com.bajiao.dto.store.StoreDetailsRequest;
import com.bajiao.entity.account.Account;
import com.bajiao.entity.cart.Cart;
import com.bajiao.entity.coupon.Coupon;
import com.bajiao.entity.discountRule.DiscountRule;
import com.bajiao.entity.discountRule.UserDiscountMark;
import com.bajiao.entity.order.CouponOrder;
import com.bajiao.entity.order.Order;
import com.bajiao.entity.order.OrderDetails;
import com.bajiao.entity.order.RefundOrder;
import com.bajiao.entity.pay.wx.WxPayResult;
import com.bajiao.entity.recharge.RechargeMenu;
import com.bajiao.entity.store.Store;
import com.bajiao.entity.user.User;
import com.bajiao.mapper.order.OrderMapper;
import com.bajiao.mapper.store.StoreMapper;
import com.bajiao.service.cart.CartService;
import com.bajiao.service.config.ConfigService;
import com.bajiao.service.coupon.CouponService;
import com.bajiao.service.discountRule.DiscountRuleService;
import com.bajiao.service.discountRule.UserDiscountMarkService;
import com.bajiao.service.order.CouponOrderService;
import com.bajiao.service.order.OrderDetailsService;
import com.bajiao.service.order.OrderService;
import com.bajiao.service.order.RefundOrderService;
import com.bajiao.service.product.ProductService;
import com.bajiao.service.recharge.RechargeMenuService;
import com.bajiao.service.store.StoreService;
import com.bajiao.service.user.UserCouponService;
import com.bajiao.service.user.UserService;
import com.bajiao.third.utils.WxPayUtils;
import com.bajiao.vo.cart.CartResponse;
import com.bajiao.vo.order.*;
import com.bajiao.vo.store.StoreDetailsResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 订单表
 * @Author: FanJq
 * @Date: 2024-12-14
 * @Version: V1.0
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Resource
    private ProductService productService;
    @Resource
    private StoreMapper storeMapper;
    @Resource
    private UserService userService;
    @Lazy
    @Resource
    private RefundOrderService refundOrderService;
    @Resource
    private DiscountRuleService discountRuleService;
    @Resource
    private UserDiscountMarkService discountMarkService;
    @Resource
    private CartService cartService;
    @Resource
    private OrderDetailsService orderDetailsService;
    @Resource
    private ConfigService configService;
    @Resource
    private WxPayUtils wxPayUtils;
    @Resource
    private RechargeMenuService rechargeMenuService;
    @Resource
    private RedisUtil redisUtil;
    @Autowired
    private CouponService couponService;
    @Autowired
    private CouponOrderService couponOrderService;
    @Autowired
    private StoreService storeService;

    /**
     * @param request
     * @return {@link ConfirmOrderResponse}
     * @Description 确认订单
     * @date 2024/12/14 14:34
     * @author FanJq
     */
    @Override
    public ConfirmOrderResponse confirm(String userId, ConfirmOrderRequest request) {
        String storeId = request.getStoreId();
        List<CartResponse> cartList = cartService.getUserCartList(userId, storeId, request.getCartIds());
        //@create by FanJq 2025/1/13 15:30 计算商品优惠金额
        Map<String, String> discountInfo = this.calculateDiscount(userId, storeId, cartList, BigDecimal.ZERO, request.getCouponId());
        List<ConfirmOrderProductResponse> productList = cartList.stream().map(cart -> {
            ConfirmOrderProductResponse productResponse = new ConfirmOrderProductResponse();
            productResponse.setProductId(cart.getProductId());
            productResponse.setProductTitle(cart.getTitle());
            productResponse.setCover(cart.getCover());
            productResponse.setPrice(cart.getPrice());
            productResponse.setBuyNum(cart.getBuyNum());
            return productResponse;
        }).collect(Collectors.toList());
        ConfirmOrderResponse response = new ConfirmOrderResponse();
        response.setProductList(productList);
        response.setBuyNum(cartList.stream().mapToInt(CartResponse::getBuyNum).sum());
        response.setProductAmount(discountInfo.get("productAmount"));
        response.setPayPrice(discountInfo.get("orderAmount"));
        response.setDiscountAmount(discountInfo.get("discountAmount"));
        StoreDetailsResponse storeDetails = storeMapper.getStoreDetails(new StoreDetailsRequest(request.getLongitude(), request.getLatitude(), request.getStoreId()));
        response.setOpenHours(storeDetails.getOpenHours());
        response.setMobile(storeDetails.getMobile());
        response.setTitle(storeDetails.getTitle());
        response.setCover(storeDetails.getCover());
        response.setStatusConv(storeDetails.getStatusConv());
        response.setStatus(storeDetails.getStatus());
        response.setDistance(storeDetails.getDistance());

        return response;
    }

    /**
     * @author wangwei
     * 下单时确认订单金额和优惠劵金额.(用户不兑换优惠劵的计算方式)
     */
    public ConfirmOrderResponse confirm1(String userId, String couponIds, ConfirmOrderRequest request) {
        String storeId = request.getStoreId();
        // 获取商品数据
        List<CartResponse> cartList = cartService.getUserCartList(userId, storeId, request.getCartIds());
        List<ConfirmOrderProductResponse> productList = cartList.stream().map(cart -> {
            ConfirmOrderProductResponse productResponse = new ConfirmOrderProductResponse();
            productResponse.setProductId(cart.getProductId());
            productResponse.setProductTitle(cart.getTitle());
            productResponse.setCover(cart.getCover());
            productResponse.setPrice(cart.getPrice());
            productResponse.setBuyNum(cart.getBuyNum());
            return productResponse;
        }).collect(Collectors.toList());

        ConfirmOrderResponse response = new ConfirmOrderResponse();
        // 未兑换优惠劵的金额计算
        if (StringUtils.isEmpty(couponIds)) {
            response.setProductList(productList);
            response.setBuyNum(cartList.stream().mapToInt(CartResponse::getBuyNum).sum());
            response.setPayPrice(countPrice(cartList).toString()); // 订单金额
            response.setDiscountAmount(String.valueOf(0));// 优惠金额
            StoreDetailsResponse storeDetails = storeMapper.getStoreDetails(new StoreDetailsRequest(request.getLongitude(), request.getLatitude(), request.getStoreId()));
            response.setOpenHours(storeDetails.getOpenHours());
            response.setMobile(storeDetails.getMobile());
            response.setTitle(storeDetails.getTitle());
            response.setCover(storeDetails.getCover());
            response.setStatusConv(storeDetails.getStatusConv());
            response.setStatus(storeDetails.getStatus());
            response.setDistance(storeDetails.getDistance());
        } else {
            Map<String, String> discountInfo = this.calculateDiscount(userId, storeId, cartList, BigDecimal.ZERO, request.getCouponId());
            response.setProductList(productList);
            response.setBuyNum(cartList.stream().mapToInt(CartResponse::getBuyNum).sum());
            response.setProductAmount(discountInfo.get("productAmount"));
            response.setPayPrice(discountInfo.get("orderAmount"));
            response.setDiscountAmount(discountInfo.get("discountAmount"));
            StoreDetailsResponse storeDetails = storeMapper.getStoreDetails(new StoreDetailsRequest(request.getLongitude(), request.getLatitude(), request.getStoreId()));
            response.setOpenHours(storeDetails.getOpenHours());
            response.setMobile(storeDetails.getMobile());
            response.setTitle(storeDetails.getTitle());
            response.setCover(storeDetails.getCover());
            response.setStatusConv(storeDetails.getStatusConv());
            response.setStatus(storeDetails.getStatus());
            response.setDistance(storeDetails.getDistance());
        }
        return response;
    }

    /**
     * 不兑换优惠劵情况下的金额计算
     *
     * @return 购物车商品总价
     */
    public BigDecimal countPrice(List<CartResponse> cartList) {
        BigDecimal money = new BigDecimal(0);
        // 原价返回
        for (CartResponse cartResponse : cartList) {
            money = money.add(new BigDecimal(cartResponse.getBuyNum().intValue()).multiply(cartResponse.getPrice()));
        }
        return money;
    }


    /**
     * @param userId
     * @param request
     * @return {@link ConfirmOrderResponse}
     * @Description 订单中心去支付
     * @date 2025/1/13 18:34
     * @author FanJq
     */
    @Override
    public ConfirmOrderResponse centerConfirm(String userId, ConfirmOrderRequest request) {
        Order order = this.getByOrderNo(userId, request.getOrderNo());
        //@create by FanJq 2025/1/13 15:30 计算商品优惠金额
        Map<String, String> discountInfo = this.calculateDiscount(userId, request.getStoreId(), null, order.getProductAmount(), request.getCouponId());
        order.setProductAmount(new BigDecimal(discountInfo.get("productAmount")));
        order.setOrderAmount(new BigDecimal(discountInfo.get("orderAmount")));
        order.setDiscountAmount(new BigDecimal(discountInfo.get("discountAmount")));
        order.setDiscountMark(Integer.parseInt(discountInfo.get("mark")));
        super.updateById(order);
        List<OrderDetails> detailsList = orderDetailsService.getByOrderNo(request.getOrderNo());
        List<ConfirmOrderProductResponse> productList = detailsList.stream().map(details -> {
            ConfirmOrderProductResponse productResponse = new ConfirmOrderProductResponse();
            productResponse.setProductId(details.getProductId());
            productResponse.setProductTitle(details.getProductTitle());
            productResponse.setCover(details.getCover());
            productResponse.setPrice(details.getPrice());
            productResponse.setBuyNum(details.getBuyNum());
            return productResponse;
        }).collect(Collectors.toList());
        ConfirmOrderResponse response = new ConfirmOrderResponse();
        response.setProductList(productList);
        response.setBuyNum(order.getBuyNum());
        response.setProductAmount(discountInfo.get("productAmount"));
        response.setPayPrice(discountInfo.get("orderAmount"));
        response.setDiscountAmount(discountInfo.get("discountAmount"));
        StoreDetailsResponse storeDetails = storeMapper.getStoreDetails(new StoreDetailsRequest(request.getLongitude(), request.getLatitude(), request.getStoreId()));
        response.setOpenHours(storeDetails.getOpenHours());
        response.setMobile(storeDetails.getMobile());
        response.setTitle(storeDetails.getTitle());
        response.setCover(storeDetails.getCover());
        response.setStatusConv(storeDetails.getStatusConv());
        response.setStatus(storeDetails.getStatus());
        response.setDistance(storeDetails.getDistance());
        return response;
    }

    /**
     * @param userId
     * @param request
     * @return {@link Order}
     * @Description 创建订单
     * @date 2024/12/14 16:43
     * @author FanJq
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Order create(String userId, CreateOrderRequest request) {
        String storeId = request.getStoreId();
        List<CartResponse> cartList = cartService.getUserCartList(userId, storeId, request.getCartIds());
        //@create by FanJq 2025/1/13 15:30 计算商品优惠金额
        Map<String, String> discountInfo = this.calculateDiscount(userId, storeId, cartList, BigDecimal.ZERO, request.getCouponId());
        Order order = new Order();
        order.setOrderNo(UUIDGenerator.getOrderNoByTime(_Whole.orderNoPrefix));
        order.setUserId(userId);
        order.setStoreId(request.getStoreId());
        order.setProductAmount(new BigDecimal(discountInfo.get("productAmount")));
        order.setOrderAmount(new BigDecimal(discountInfo.get("orderAmount")));
        order.setDiscountAmount(new BigDecimal(discountInfo.get("discountAmount")));
        order.setBuyNum(cartList.stream().mapToInt(CartResponse::getBuyNum).sum());
        if (order.getBuyNum() <= 0)
            throw new DataHandleException("请添加要购买的商品");
        order.setPayPrice(order.getOrderAmount());
        order.setPayType(request.getPayWay());
        order.setRemark(request.getRemark());
        order.setDiscountMark(Integer.parseInt(discountInfo.get("mark")));
        order.setExpireTime(DateUtil.addMinute(new Date(), 30));
        if (super.save(order)) {
            //@create by FanJq 2025/1/13 19:12 创建子订单
            orderDetailsService.create(order, cartList);
        }
        List<String> cartIdList = cartList.stream().map(CartResponse::getId).collect(Collectors.toList());
        cartService.removeByIds(cartIdList);
        redisUtil.set(_Whole.orderExpiredKey + order.getId(), order.getId(), 60 * 30);
        return order;
    }

    /**
     * @param user
     * @param request
     * @return {@link String}
     * @Description 订单支付
     * @date 2024/12/14 16:39
     * @author FanJq
     */
    @Override
    //@Transactional(rollbackFor = Exception.class)
    public Object toPay(User user, CreateOrderRequest params, HttpServletRequest request) {
        String userId = user.getId();
        Store store = storeMapper.selectById(params.getStoreId());
        if (ObjectUtil.isNull(store) || store.getStatus() != 1 || store.getDelFlag() == 1)
            throw new DataHandleException("店铺信息不存在");
        Order order = null;
        if (params.getType() == 1) {
            //@create by FanJq 2025/1/13 18:56 创建订单
            order = this.create(userId, params);
            // 绑定
        } else {
            order = this.getByOrderNo(userId, params.getOrderNo());
        }
        BigDecimal payPrice = order.getPayPrice();
        if (params.getPayWay() == 1) {
            Account account = userService.getAccount(userId);
            if (payPrice.compareTo(account.getMoney()) > _Whole.ZERO) {
                BigDecimal lackAmount = payPrice.subtract(account.getMoney());
                RechargeMenu rechargeMenu = rechargeMenuService.lambdaQuery()
                        .ge(RechargeMenu::getAmount, lackAmount)
                        .orderByAsc(RechargeMenu::getAmount)
                        .last("LIMIT 1").one();
                if (ObjectUtil.isNull(rechargeMenu)) {
                    rechargeMenu = rechargeMenuService.lambdaQuery()
                            .orderByDesc(RechargeMenu::getAmount)
                            .last("LIMIT 1").one();
                }
                throw new DataHandleException(String.format("下单金额美豆不足，请前往充值美豆充%s送%s",
                        rechargeMenu.getAmount().stripTrailingZeros().toPlainString(),
                        rechargeMenu.getGiveAmount().stripTrailingZeros().toPlainString()
                ), 5);
            }
            userService.changeMoney(userId, payPrice, _Whole.TWO, order.getOrderNo(), "购买商品", _Whole.THREE);

            // 绑定优惠劵和该订单的关系
            if (!params.getCouponIds().isEmpty()) {
                String[] arr = params.getCouponIds().split(",");
                for (String orderNo : arr) {
                    CouponOrder couponOrder = couponOrderService.getOne(new QueryWrapper<CouponOrder>().lambda().eq(CouponOrder::getOrderNo, orderNo));
                    couponOrder.setOrderId(order.getOrderNo());
                    couponOrderService.updateById(couponOrder);
                }
            }

            //@create by FanJq 2024/12/14 17:39 支付完成事件
            this.complete(order);
            return order.getOrderNo();
        } else if (params.getPayWay() == 2) {
            String callback = configService.getCallback("wxOrder");
            if (StrUtil.isBlank(callback) || !callback.contains("http"))
                throw new DataHandleException("支付失败，请检查支付配置");
            String payNo = UUIDGenerator.getOrderNoByTime("");
            super.lambdaUpdate().set(Order::getPayNo, payNo).eq(Order::getId, order.getId()).update();
            String source = params.getSource();
            String result = "";
            if (source.equals("applet")) {
                if (StrUtil.isBlank(user.getOpenId()))
                    throw new DataHandleException("openId不存在，支付失败");
                //@create by FanJq 2024/12/25 11:16 小程序支付
                result = wxPayUtils.miniAppPay(request, user.getOpenId(), payNo, String.valueOf(payPrice), "购买商品", callback, "");
            } else {
                //@create by FanJq 2024/12/25 11:16 app支付
                result = wxPayUtils.payApp(request, payNo, String.valueOf(payPrice), "购买商品", callback, "");
            }
            if (StrUtil.isBlank(result))
                throw new DataHandleException("支付失败");
            return WxPayResult.WxPayResultBuilder.aWxPayResult()
                    .orderNo(order.getOrderNo())
                    .orderId(order.getId())
                    .result(FastJsonHelper.toBean(result, Map.class))
                    .payMoney(payPrice)
                    .build();
        }
        return order.getOrderNo();
    }

    /**
     * @Description 支付完成
     * @date 2024/12/14 17:21
     * @author FanJq
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void complete(Order order) {
        //order.setPayType(_Whole.ONE);
        order.setPayTime(new Date());
        order.setStatus(_Whole.ONE);
        order.setVerifyCode(this.getVerifyCode());
        //discountMarkService.modify(order.getUserId(), order.getStoreId(), order.getDiscountMark());
        List<OrderDetails> detailsList = orderDetailsService.getByOrderNo(order.getOrderNo());
        //List<String> productIds = detailsList.stream().map(OrderDetails::getProductId).collect(Collectors.toList());
        detailsList.forEach(details -> {
            productService.salesLogic(details.getProductId(), _Whole.ONE, details.getBuyNum());
        });
        super.updateById(order);
    }

    /**
     * @param userId
     * @param status
     * @return {@link List< OrderResponse>}
     * @Description 获取订单分页列表
     * @date 2024/12/16 16:56
     * @author FanJq
     */
    @Override
    public List<OrderResponse> getOrderPage(String userId, Integer status) {
        if (status.intValue() > 9)
            status = null;
        List<OrderResponse> responseList = super.baseMapper.getOrderPage(userId, status);
        responseList.forEach(response -> {
            response.setOrderDetails(orderDetailsService.getByOrderNo(response.getOrderNo()));
            if (response.getStatus() == 0 && ObjectUtil.isNotNull(response.getExpireTime())) {
                response.setExpireTimeStamp(response.getExpireTime().getTime() / 1000);
            }
        });
        return responseList;
    }

    /**
     * @param userId
     * @param orderNo
     * @return
     * @Description 取消订单
     * @date 2024/12/16 17:45
     * @author FanJq
     */
    @Override
    public void cancel(String userId, String orderNo) {
        Order order = this.getByOrderNo(userId, orderNo);
        if (ObjectUtil.isNull(order))
            throw new DataHandleException("订单不存在");
        if (order.getStatus() != _Whole.ZERO)
            throw new DataHandleException("当前订单不支持取消");
        //@create by FanJq 2024/12/16 17:51 更新订单状态
        super.lambdaUpdate()
                .set(Order::getStatus, _Whole.NINE)
                .eq(Order::getOrderNo, orderNo)
                .eq(Order::getUserId, userId)
                .update();
    }

    /**
     * @param userId
     * @param orderNo
     * @return
     * @Description 申请退款
     * @date 2024/12/19 11:42
     * @author FanJq
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void askRefund(String userId, String orderNo, String reason) {
        Order order = this.getByOrderNo(userId, orderNo);
        if (ObjectUtil.isNull(order))
            throw new DataHandleException("订单不存在");
        if (order.getStatus() != _Whole.ONE)
            throw new DataHandleException("当前订单不支持退款");
        //@create by FanJq 2024/12/19 14:28 创建退款单
        RefundOrder refundOrder = refundOrderService.create(order, reason);
        //@create by FanJq 2024/12/19 14:32 更新订单状态
        super.lambdaUpdate()
                .set(Order::getStatus, _Whole.SEVEN)
                .eq(Order::getId, order.getId())
                .update();
        if (refundOrder.getRefundPrice().signum() <= _Whole.ZERO) {
            //@create by FanJq 2024/12/19 17:22 直接走退款通过逻辑
            refundOrderService.approve(refundOrder, _Whole.ONE);
        }
    }


    /**
     * @param order
     * @param userCouponId
     * @return {@link Order}
     * @Description 计算优惠金额
     * @date 2024/12/14 15:03
     * @author FanJq
     */
    public Order calculateCoupon(Order order, String userCouponId) {
//        order.setDiscountAmount(BigDecimal.ZERO);
//        if (StrUtil.isBlank(userCouponId))
//            return order;
//        UserCoupon userCoupon = userCouponService.getById(order.getUserId(), userCouponId);
//        if (ObjectUtil.isNull(userCoupon))
//            throw new DataHandleException(userCoupon.getTitle() + "优惠券不存在");
//        if (userCoupon.getStatus().intValue() != _Whole.ONE)
//            throw new DataHandleException(userCoupon.getTitle() + "优惠券已失效");
//        if (userCoupon.getScope() == _Whole.TWO && !userCoupon.getStoreId().equals(order.getStoreId()))
//            throw new DataHandleException(userCoupon.getTitle() + "非商家专属券");
//        order.setUserCouponId(userCouponId);
//        //@create by FanJq 2024/12/14 14:52 计算优惠金额
//        BigDecimal quota = userCoupon.getQuota();
//        //@create by FanJq 2024/12/14 14:55 优惠后金额
//        BigDecimal afterPrice = BigDecimal.ZERO;
//        switch (userCoupon.getType()) {
//            case 1: //@create by FanJq 2024/12/14 14:53 折扣券
//                //@create by FanJq 2024/12/14 14:55 优惠金额
//                afterPrice = order.getPriceAmount().multiply(quota).setScale(_Whole.TWO, RoundingMode.HALF_UP);
//                BigDecimal discountPrice = order.getPriceAmount().subtract(afterPrice);
//                order.setDiscountAmount(discountPrice);
//                break;
//            case 2: //@create by FanJq 2024/12/14 14:53 抵扣券
//                afterPrice = order.getPriceAmount().subtract(quota);
//                if (afterPrice.signum() <= _Whole.ZERO) {
//                    //@create by FanJq 2024/12/14 15:01 抵扣金额大于商品总金额
//                    order.setDiscountAmount(order.getPriceAmount());
//                } else {
//                    order.setDiscountAmount(quota);
//                }
//                break;
//        }
//        return order;
        return null;
    }

    /**
     * @param
     * @return {@link String}
     * @Description 获取核销码
     * @date 2024/12/14 17:29
     * @author FanJq
     */
    public String getVerifyCode() {
        String verifyCode = UUIDGenerator.getRandom620(13);
        Integer count = super.lambdaQuery()
                .select(Order::getId)
                .eq(Order::getVerifyCode, verifyCode)
                .count();
        if (count > _Whole.ZERO)
            this.getVerifyCode();
        return verifyCode;
    }

    /**
     * @param userId
     * @param orderNo
     * @return {@link Order}
     * @Description 根据订单编号获取
     * @date 2024/12/16 17:47
     * @author FanJq
     */
    @Override
    public Order getByOrderNo(String userId, String orderNo) {
        Order order = super.lambdaQuery()
                .eq(Order::getUserId, userId)
                .eq(Order::getOrderNo, orderNo)
                .one();
        return order;
    }

    /**
     * @param payNo
     * @return {@link Order}
     * @Description 根据订单编号获取
     * @date 2025/1/13 19:42
     * @author FanJq
     */
    @Override
    public Order getByPayNo(String payNo) {
        Order order = super.lambdaQuery()
                .eq(Order::getPayNo, payNo)
                .one();
        return order;
    }

    /**
     * @param verifyCode
     * @return {@link Order}
     * @Description 根据核销码获取
     * @date 2024/12/26 14:16
     * @author FanJq
     */
    public Order getByVerifyCode(String storeId, String verifyCode) {
        Order order = super.lambdaQuery()
                .eq(Order::getStoreId, storeId)
                .eq(Order::getVerifyCode, verifyCode)
                .one();
        return order;
    }

    /**
     * @param userId
     * @param orderNo
     * @return {@link OrderDetailsResponse}
     * @Description 获取订单详情
     * @date 2024/12/19 16:38
     * @author FanJq
     */
    @Override
    public OrderDetailsResponse getDetails(String userId, String orderNo) {
        OrderDetailsResponse response = super.baseMapper.getDetails(userId, orderNo);
        List<OrderDetails> detailsList = orderDetailsService.getByOrderNo(orderNo);
        response.setOrderDetails(detailsList);
        if (response.getStatus().intValue() == _Whole.ONE) {
            //@create by FanJq 2024/12/19 17:05 生成核销码
            response.setVerifyQrCode(buildVerifyQrCode(response.getVerifyCode()));
        }
        if (response.getStatus().intValue() == _Whole.SEVEN || response.getStatus().intValue() == _Whole.EIGHT) {
            //@create by FanJq 2024/12/19 17:05 组建退款数据
            RefundOrder refundOrder = refundOrderService.getByOrderNo(orderNo);
            if (ObjectUtil.isNotNull(refundOrder)) {
                response.setRefundOrderNo(refundOrder.getRefundOrderNo());
                response.setRefundPrice(refundOrder.getRefundPrice());
                response.setRefundTimeStr(DateUtils.time_sdf.get().format(refundOrder.getCreateTime()));
                response.setReason(refundOrder.getReason());
            }
        }
        List<CouponOrder> couponOrderList = couponOrderService.list(new QueryWrapper<CouponOrder>().lambda().eq(CouponOrder::getOrderId, orderNo));
        if(!couponOrderList.isEmpty()) {
            List<String> couponIds = couponOrderList.stream().map(data -> {
                return data.getCouponId();
            }).collect(Collectors.toList());
            response.setCouponIdList(couponIds);
        }
        return response;
    }

    /**
     * @param refundOrder
     * @param status
     * @return
     * @Description 订单执行退款逻辑
     * @date 2024/12/19 17:28
     * @author FanJq
     */
    @Override
    //@Async("taskExecutor")
    public void refundLogic(RefundOrder refundOrder, int status) {
        Order order = this.getByOrderNo(refundOrder.getUserId(), refundOrder.getOrderNo());
        if (order.getStatus().intValue() != _Whole.SEVEN) return;
        int orderStatus = status == _Whole.ONE ? _Whole.EIGHT : _Whole.ONE;
        boolean b = super.lambdaUpdate()
                .set(Order::getStatus, orderStatus)
                .eq(Order::getId, order.getId())
                .update();
        if (b && status == _Whole.ONE) {
            //@create by FanJq 2024/12/19 17:49 更新产品销量
            List<OrderDetails> detailsList = orderDetailsService.getByOrderNo(order.getOrderNo());
            //List<String> productIds = detailsList.stream().map(OrderDetails::getProductId).collect(Collectors.toList());
            detailsList.forEach(details -> {
                productService.salesLogic(details.getProductId(), _Whole.TWO, details.getBuyNum());
            });
        }
    }

    /**
     * @param verifyCode
     * @return {@link String}
     * @Description 扫码核销
     * @date 2024/12/26 14:15
     * @author FanJq
     */
    @Override
    public String scanCode(String storeId, String verifyCode) {
        Order order = this.getByVerifyCode(storeId, verifyCode);
        if (ObjectUtil.isNull(order))
            throw new DataHandleException("未找到订单信息");
        if (!StrUtil.equals(storeId, order.getStoreId()))
            throw new DataHandleException("非本店铺订单，核销失败");
        if (order.getStatus() != _Whole.ONE)
            throw new DataHandleException("订单状态异常，无法核销");
        //@create by FanJq 2024/12/26 14:19 更新订单状态
        super.lambdaUpdate()
                .set(Order::getStatus, _Whole.TWO)
                .set(Order::getVerifyTime, new Date())
                .eq(Order::getId, order.getId())
                .eq(Order::getStatus, _Whole.ONE)
                .update();
        return order.getOrderNo();
    }

    /**
     * @param orderNo
     * @param keywords
     * @param productTitle
     * @param status
     * @param createTimeBegin
     * @param createTimeEnd
     * @return {@link List< OrderAdmin>}
     * @Description 管理后台列表
     * @date 2025/1/7 17:39
     * @author FanJq
     */
    @Override
    public List<OrderAdmin> getAdminList(String orderNo, String keywords, String productTitle, Integer status, String createTimeBegin, String createTimeEnd) {
        if (StrUtil.isAllNotBlank(createTimeBegin, createTimeEnd))
            createTimeEnd = createTimeEnd + " 23:59:59";
        List<OrderAdmin> resultList = super.baseMapper.getAdminList(orderNo, keywords, productTitle, status, createTimeBegin, createTimeEnd);
        resultList.forEach(model -> {
            List<OrderDetailsAdmin> detailsList = new ArrayList<>();
            orderDetailsService.getByOrderNo(model.getOrderNo()).forEach(i -> {
                detailsList.add(FastJsonHelper.beanToBean(i, OrderDetailsAdmin.class));
            });
            model.setOrderDetails(detailsList);
        });
        return resultList;
    }

    /**
     * @param
     * @return {@link Map< String, Object>}
     * @Description 订单统计
     * @date 2025/2/12 11:42
     * @author FanJq
     */
    @Override
    public Map<String, Object> getOrderStat() {
        Map<String, Object> result = this.baseMapper.getOrderStat();
        return result;
    }

    /**
     * @param userId
     * @param storeId
     * @return {@link String}
     * @Description 获取优惠提示
     * @date 2025/1/13 14:41
     * @author FanJq
     */
    @Override
    public String getDiscountTips(String userId, String storeId) {
        List<DiscountRule> ruleList = discountRuleService.getByStoreId(storeId);
        String tip = "";
        if (CollectionUtil.isNotEmpty(ruleList)) {
            //UserDiscountMark userStoreMark = discountMarkService.getUserStoreMark(userId, storeId);
            Integer index = 0;
//            if (ObjectUtil.isNotNull(userStoreMark)) {
//                index = userStoreMark.getNextMark() >= ruleList.size() ? 0 : userStoreMark.getNextMark();
//            }
            DiscountRule rule = ruleList.get(index);
            tip = "再买" + rule.getMeet().stripTrailingZeros().toPlainString() +
                    "可享受减" + rule.getDiscountAmount().stripTrailingZeros().toPlainString() + "的优惠";
        }
        return tip;
    }

    /**
     * @param userId
     * @param storeId
     * @param cartIds
     * @return {@link Map< String, String>}
     * @Description 计算购物车价格
     * @date 2025/1/13 16:34
     * @author FanJq
     */
    @Override
    public Map<String, String> getCartAmount(String userId, String storeId, String cartIds) {
        List<CartResponse> cartList = new ArrayList<>();
        if (StrUtil.isNotBlank(cartIds)) {
            cartList = cartService.getUserCartList(userId, storeId, cartIds);
        } else {
            cartList = new ArrayList<>();
        }
        Map<String, String> resultMap = this.calculateDiscount(userId, storeId, cartList, BigDecimal.ZERO, "0");
        return resultMap;
    }

    /**
     * @param userId
     * @param storeId
     * @param userCartList
     * @return {@link Map< String, String>}
     * @Description 计算优惠金额
     * @date 2025/1/13 15:39
     * @author FanJq
     */
    private Map<String, String> calculateDiscount(String userId, String storeId, List<CartResponse> userCartList, BigDecimal productAmount, String couponId) {
        Map<String, String> resultMap = new HashMap<>();
        //@create by FanJq 2025/1/13 15:06 商品总价
        if (CollectionUtil.isNotEmpty(userCartList)) {
            productAmount = userCartList.stream().map(CartResponse::getProductPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        resultMap.put("productAmount", productAmount.stripTrailingZeros().toPlainString());
        List<DiscountRule> ruleList = discountRuleService.getByStoreId(storeId);
        if (CollectionUtil.isEmpty(ruleList)) {
            resultMap.put("orderAmount", productAmount.stripTrailingZeros().toPlainString());
            resultMap.put("discountAmount", "0");
            resultMap.put("mark", "0");
            resultMap.put("tip", "");
            return resultMap;
        }
        //@create by FanJq 2025/1/13 15:26 存在优惠政策 开始计算优惠
//        UserDiscountMark userStoreMark = discountMarkService.getUserStoreMark(userId, storeId);
//        if (ObjectUtil.isNull(userStoreMark)) {
//            userStoreMark = new UserDiscountMark();
//            userStoreMark.setUserId(userId);
//            userStoreMark.setStoreId(storeId);
//            //@create by FanJq 2025/1/13 14:48 数组下标 从0开始
//            userStoreMark.setMark(0);
//            userStoreMark.setNextMark(0);
//            discountMarkService.save(userStoreMark);
//        }
        Boolean flag = Boolean.TRUE;
        BigDecimal orderAmount = productAmount;
        //@create by FanJq 2025/1/13 15:09 优惠金额
        BigDecimal discountAmount = BigDecimal.ZERO;
        Integer next = 0;

        while (flag) {
            next = next >= ruleList.size() ? 0 : next;
            DiscountRule rule = ruleList.get(next);
            if (productAmount.compareTo(rule.getMeet()) >= 0) {
                productAmount = productAmount.subtract(rule.getMeet());
                discountAmount = discountAmount.add(rule.getDiscountAmount());
                next = next + 1 >= ruleList.size() ? 0 : next + 1;
            } else flag = false;
        }
        DiscountRule rule = ruleList.get(next);
        String discountTip = "再买" + (rule.getMeet().subtract(productAmount)).stripTrailingZeros().toPlainString() +
                "可享受减" + rule.getDiscountAmount().stripTrailingZeros().toPlainString() + "的优惠";

        resultMap.put("orderAmount", orderAmount.subtract(discountAmount).stripTrailingZeros().toPlainString());
        resultMap.put("discountAmount", discountAmount.stripTrailingZeros().toPlainString());
        resultMap.put("mark", String.valueOf(next == 0 ? 0 : next - 1));
        resultMap.put("tip", discountTip);
        return resultMap;
    }

    /**
     * @param verifyCode
     * @return {@link String}
     * @Description 生成核销二维码
     * @date 2024/12/26 11:49
     * @author FanJq
     */
    private String buildVerifyQrCode(String verifyCode) {
        Map<String, String> params = new HashMap<String, String>() {{
            put("a", "product");
            put("b", verifyCode);
            put("c", oConvertUtils.randomGen(3));
        }};
        String jsonString = JSONObject.toJSONString(params);
        String encrypt = AesEncryptUtil.encrypt(jsonString);
        return QrCodeUtil.generateAsBase64(encrypt, new QrConfig(), "png");
    }

    /**
     * @param order
     * @return
     * @Description 订单过期事件
     * @date 2025/2/19 19:01
     * @author FanJq
     */
    @Override
    @Async("taskExecutor")
    public void expiredEvent(Order order) {
        super.lambdaUpdate()
                .set(Order::getStatus, _Whole.NINE)
                .eq(Order::getStatus, _Whole.ZERO)
                .eq(Order::getId, order.getId())
                .update();
    }

    @Override
    public List<CouponDto> queryCouponTypeByStore(String userId, String storeId) {
        // 获取当前时间
        List<Coupon> couponList = couponService.list(
                new QueryWrapper<Coupon>().lambda().eq(Coupon::getStoreId, storeId).eq(Coupon::getStatus, CouponStatusEnum.USE.getType())
        );
        List<CouponDto> list = couponList.stream().map(data -> {
            CouponDto dto = new CouponDto();
            BeanUtils.copyProperties(data, dto);
            Store store = storeService.getById(data.getStoreId());
            dto.setStoreName(store.getTitle());
            return dto;
        }).collect(Collectors.toList());

        return list;
    }

    @Override
    public List<CouponCountDto> queryCouponNumber(String userId, String storeId, String cartIds) {
        // 查询店铺下的满减规则
        List<DiscountRule> ruleList = discountRuleService.getByStoreId(storeId);
        if (CollectionUtil.isEmpty(ruleList)) {
            return null;
        }

        // 根据订单金额和满减规则,计算所需的优惠劵类型
        ruleList = ruleList.stream().sorted(Comparator.comparing(DiscountRule::getSeq)).collect(Collectors.toList());

        List<CartResponse> cartList = cartService.getUserCartList(userId, storeId, cartIds);
        BigDecimal b = countPrice(cartList);
        double orderAmount = b.doubleValue();

        List<BigDecimal> list = ruleList.stream().map(data -> {
            return data.getDiscountAmount();
        }).collect(Collectors.toList());
        List<CouponCountDto> result = couponCount(list, orderAmount, storeId);
        return result;
    }

//    public List<CouponCountDto> couponCount(List<BigDecimal> list, double orderAmount, String storeId) {
//        // 去重满减规则数据
//        List<BigDecimal> uniqueList = list.stream()
//                .distinct()
//                .collect(Collectors.toList());
//        List<CouponCountDto> resule = new ArrayList<>();
//        uniqueList.forEach(data -> {
//            CouponCountDto dto = new CouponCountDto();
//            dto.setPrice(data);
//            dto.setNumber(0);
//            // 查找店铺指定金额优惠劵信息
//            Coupon coupon = couponService.getOne(new QueryWrapper<Coupon>().lambda().eq(Coupon::getStoreId, storeId).eq(Coupon::getPrice, data));
//            dto.setCouponId(coupon.getId());
//            resule.add(dto);
//        });
//
//        // 记录使用的优惠券数量和总优惠金额
//        int totalCouponCount = 0;
//        double totalDiscount = 0;
//        // 当前使用的优惠券索引
//        int couponIndex = 0;
//        // 每500元一个循环
//        while (orderAmount >= 100) {
//            // 计算当前循环的满减次数
//            int fullCycles = (int) (orderAmount / 500); // 完整500元循环次数
//            // 在完整500元循环内使用优惠券
//            for (int i = 0; i <= fullCycles; i++) {
//                for (int j = 0; j < 5; j++) {
//                    if (orderAmount >= 100) {
//                        totalCouponCount++;
////                            totalDiscount += couponDiscounts[couponIndex];
//                        orderAmount -= 100; // 每满100元使用一张优惠券
//                        BigDecimal s = list.get(couponIndex); // 优惠价格
//
//                        // 如果当前集合已经包含该数据, 则数量递增
//                        for (CouponCountDto dto : resule) {
//                            if(dto.getPrice().equals(s)){
//                                dto.setNumber(dto.getNumber() + 1);
//                            }else{
//                                // 查找店铺指定金额优惠劵信息
//                                Coupon coupon = couponService.getOne(new QueryWrapper<Coupon>().lambda().eq(Coupon::getStoreId, storeId).eq(Coupon::getPrice, s));
//                                dto = new CouponCountDto();
//                                dto.setCouponId(coupon.getId());
//                                dto.setPrice(s);
//                                dto.setNumber(1);
//                            }
//                        }
//                        couponIndex = (couponIndex + 1) % 5; // 循环使用优惠券
//                    } else {
//                        break;
//                    }
//                }
//            }
//
//            // 处理剩余金额
//            while (orderAmount >= 100) {
//                totalCouponCount++;

//                  totalDiscount += couponDiscounts[couponIndex];
//                orderAmount -= 100; // 每满100元使用一张优惠券
//                couponIndex = (couponIndex + 1) % 5; // 循环使用优惠券
//            }
//            break; // 退出循环
//        }
//        return resule;
//    }
    public List<CouponCountDto> couponCount(List<BigDecimal> list, double orderAmount, String storeId) {
        List<CouponCountDto> resule = new ArrayList<>();

        // 记录使用的优惠券数量和总优惠金额
        int totalCouponCount = 0;
        double totalDiscount = 0;
        // 当前使用的优惠券索引
        int couponIndex = 0;
        // 每500元一个循环
        while (orderAmount >= 100) {
            // 计算当前循环的满减次数
            int fullCycles = (int) (orderAmount / 500); // 完整500元循环次数
            // 在完整500元循环内使用优惠券
            for (int i = 0; i <= fullCycles; i++) {
                for (int j = 0; j < 5; j++) {
                    if (orderAmount >= 100) {
                        totalCouponCount++;
//                            totalDiscount += couponDiscounts[couponIndex];
                        orderAmount -= 100; // 每满100元使用一张优惠券
                        BigDecimal s = list.get(couponIndex); // 优惠价格

                        // 查找店铺指定金额优惠劵信息
                        Coupon coupon = couponService.getOne(new QueryWrapper<Coupon>().lambda().eq(Coupon::getStoreId, storeId).eq(Coupon::getPrice, s));
                        CouponCountDto dto = new CouponCountDto();
                        dto.setCouponId(coupon.getId());
                        dto.setPrice(s);
                        dto.setNumber(1);
                        resule.add(dto);
                        couponIndex = (couponIndex + 1) % 5; // 循环使用优惠券
                    } else {
                        break;
                    }
                }
            }

            // 处理剩余金额
            while (orderAmount >= 100) {
                totalCouponCount++;
//                totalDiscount += couponDiscounts[couponIndex];
                orderAmount -= 100; // 每满100元使用一张优惠券
                couponIndex = (couponIndex + 1) % 5; // 循环使用优惠券
            }
            break; // 退出循环
        }
        return resule;
    }

    @Override
    public List<EncodeMenuOrderDetails> orderMenuDetails(String userId, String storeId, String orderId) {
        // 获取优惠劵列表
        List<EncodeMenuOrderDetails> couponList = orderDetailsService.list(
                new QueryWrapper<OrderDetails>().lambda()
                        .eq(OrderDetails::getStoreId, storeId)
                        .eq(OrderDetails::getOrderNo, orderId)
        ).stream().map(data -> {
            EncodeMenuOrderDetails details = new EncodeMenuOrderDetails();
            BeanUtils.copyProperties(data, details);
            Order order = this.getByOrderNo(userId, orderId);
            details.setOrderAmount(order.getOrderAmount());
            details.setDiscountAmount(order.getDiscountAmount());
            details.setProductAmount(order.getProductAmount());
            return details;
        }).collect(Collectors.toList());

        return couponList;
    }

}
